/*
* @(#)Editor.java
*
* Copyright (c) 2004 DCIVision Ltd
* All rights reserved.
*
* This software is the confidential and proprietary information of DCIVision
* Ltd ("Confidential Information").  You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the license
* agreement you entered into with DCIVision Ltd.
*/

package com.dcivision.workflow.applet.editor;

//import graphtreemodel.GraphTreeModel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.event.UndoableEditEvent;

import org.jgraph.JGraph;
import org.jgraph.event.GraphSelectionEvent;
import org.jgraph.event.GraphSelectionListener;
import org.jgraph.graph.AttributeMap;
import org.jgraph.graph.BasicMarqueeHandler;
import org.jgraph.graph.CellMapper;
import org.jgraph.graph.CellView;
import org.jgraph.graph.ConnectionSet;
import org.jgraph.graph.DefaultEdge;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.DefaultGraphModel;
import org.jgraph.graph.DefaultPort;
import org.jgraph.graph.Edge;
import org.jgraph.graph.EdgeView;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.GraphModel;
import org.jgraph.graph.GraphUndoManager;
import org.jgraph.graph.ParentMap;
import org.jgraph.graph.Port;
import org.jgraph.graph.PortView;
import org.jgraph.layout.CircleGraphLayout;
import org.jgraph.layout.JGraphLayoutAlgorithm;
import org.jgraph.layout.SugiyamaLayoutAlgorithm;
import org.jgraph.pad.DefaultGraphModelFileFormatXML;
import org.jgraph.pad.GPGraph;
import org.jgraph.pad.GPUserObject;
import org.jgraph.pad.ImageCell;
import org.jgraph.pad.actions.FormatRoutingParallel;
import org.jgraph.util.JGraphUtilities;

import com.dcivision.dms.client.HtmlFormText;
import com.dcivision.framework.Utility;
import com.dcivision.workflow.applet.AppletConstant;
import com.dcivision.workflow.applet.AppletResource;
import com.dcivision.workflow.applet.WindowUtilities;
import com.dcivision.workflow.applet.net.HttpOperation;
import com.dcivision.workflow.bean.MtmWorkflowStepWorkflowStep;
import com.dcivision.workflow.bean.WorkflowStep;

/**
    Editor.java
    
    @author          Beyond
    @company         DCIVision Limited
    @creation date   27/08/2004
    @version         $Revision: 1.20 $
    */

public class Editor 
  extends JPanel
  implements GraphSelectionListener, KeyListener {
  ActionListener[] actionListeners;
  // JGraph instance
  protected GPGraph graph;

  public JTextArea messageTextArea;
  
  // Undo Manager
  protected GraphUndoManager undoManager;
  
  
  public final static Color START_COLOR = new Color(0, 52, 102);
  public final static Color END_COLOR  = new Color(150, 30, 30);    
  public final static Color BLANK_COLOR = new Color(255,255,255);  
  public final static Color STEP_OFFSET_COLOR = new Color(0, 84, 135);  
  public final static Color STEP_SPLIT_COLOR = new Color(0, 84, 185);
  public final static Color STEP_TODO_COLOR = new Color(0, 84, 165);  

  /*
  public final static Color LINE_TODO_COLOR = new Color(241,96,34);  
  public final static Color LINE_YES_COLOR = new Color(241,96,34);
  public final static Color LINE_NOT_COLOR = new Color(241,96,34);
  public final static Color LINE_CUSTOM_COLOR = new Color(241,96,34);  
  */
  
  public final static String CONNECTNAME_YES = "Yes" ;
  public final static String CONNECTNAME_NOT = "No" ;
  public final static String CONNECTNAME_TODO = "To Do" ;  
  public final static String CONNECTNAME_CUSTOM = "U_" ;
  public final static String CONNECTNAME_FORM_VALUE_DRIVEN = "D_" ;
  public final static String CONNECTNAME_AUTO_TASK = "A_" ;
  public final static String CONNECTNAME_APPROVE = "Approve" ;
  public final static String CONNECTNAME_REJECT = "Reject" ;
  public final static String CONNECTNAME_RETURN = "Return" ;
  
  
  
  public final static String CONNECTNAME_YES_DB = "T" ;
  public final static String CONNECTNAME_NOT_DB = "F" ;
  public final static String CONNECTNAME_TODO_DB = "S" ;  
  public final static String CONNECTNAME_CUSTOM_DB = "S" ;
  public final static String CONNECTNAME_FORM_DB = "S" ;
  public final static String CONNECTNAME_APPROVE_DB = "A" ;
  public final static String CONNECTNAME_REJECT_DB = "R" ;

  
  
  public final static Color LINE_TODO_COLOR = Color.BLUE ;  
  public final static Color LINE_YES_COLOR = Color.GREEN ;
  public final static Color LINE_NOT_COLOR = Color.RED;
  public final static Color LINE_APPROVE_COLOR = Color.MAGENTA ;
  public final static Color LINE_REJECT_COLOR = Color.ORANGE;
  public final static Color LINE_CUSTOM_COLOR = new Color(241,96,34);  
  public final static Color LINE_RETURN_COLOR = new Color(241,50,60);
  public final static Color LINE_FORM_COLOR =  Color.MAGENTA;
  public final static Color LINE_AUTO_TASK_COLOR =  Color.BLUE;
  public final static int SELECTED_NONE = 0 ;
  public final static int SELECTED_TYPE_STEP_OFFSET = 1 ; 
  public final static int SELECTED_TYPE_STEP_SPLIT = 2 ;
  public final static int SELECTED_TYPE_STEP_TODO = 3 ;
  
  public final static int SELECTED_TYPE_LINE_TODO = 4 ;
  public final static int SELECTED_TYPE_LINE_YES = 5 ;    
  public final static int SELECTED_TYPE_LINE_NOT = 6 ;
  public final static int SELECTED_TYPE_LINE_CUSTOM = 7 ;
  public final static int SELECTED_TYPE_LINE_RETURN = 8 ;
  public final static int SELECTED_TYPE_LINE_APPROVE = 9 ;
  public final static int SELECTED_TYPE_LINE_REJECT = 10 ;
  public final static int SELECTED_TYPE_FORM_VALUE_DRIVEN = 11 ;
  public final static int SELECTED_TYPE_AUTO_TASK = 12 ;
  public final static String STEP_START = "START";
  public final static String STEP_OFFSET = "OFFSET";
  public final static String STEP_SPLIT = "SPLIT";
  public final static String STEP_TODO = "TODO";
  public final static String STEP_END = "END";
  public final static String NEW_STEP = "New Step";
  
  protected int stepNum ; 
  protected String stepDefaultName ;
  protected  String actionType=null;
  private Color selectedColor;      
  private int selectedType ;
  private String selectedTypeName ;
  private boolean ispending ;
  
  
  private String selectedConnectName ;
  private String selectedConnectType ;
  //private ButtonGroup toolbarGroup = new ButtonGroup(); 
  
  public ButtonGroup toolTipMenuGroup = new ButtonGroup();
  
  public JButton [] toggleButtons;

  public boolean enable ;
  
  public Integer workflowRecordID = null;
  
  public List workflowStepList = null;
  
  public String hostURL = "";
  private HttpOperation httpOperation = null;
  JComboBox jCBzoom = new JComboBox();

    //
    // Editor Panel
    //

    // Construct an Editor Panel
    public Editor(String hostURL){
        this.hostURL = hostURL ;
        
        stepNum = 0; 
        stepDefaultName = "Step";       
        
        selectedType = SELECTED_NONE ;
        selectedColor = BLANK_COLOR;
        
        selectedConnectName = "";
        
        // Use Border Layout
        setLayout(new BorderLayout());
        // Construct the Graph
        graph = new MyGraph(new MyModel());
      
        
        // Construct Command History
        //
        // Create a GraphUndoManager which also Updates the ToolBar
        undoManager = new GraphUndoManager() {
                // Override Superclass
            public void undoableEditHappened(UndoableEditEvent e) {
                    // First Invoke Superclass
                super.undoableEditHappened(e);
                // Then Update Undo/Redo Buttons
                updateHistoryButtons();
            }
        };
    
        // Add Listeners to Graph
        //
        // Register UndoManager with the Model
        graph.getModel().addUndoableEditListener(undoManager);
        // Update ToolBar based on Selection Changes
        graph.getSelectionModel().addGraphSelectionListener(this);
        // Listen for Delete Keystroke when the Graph has Focus
        graph.addKeyListener(this);
    
        // Construct Panel
        //
        // Add a ToolBar
        //add(createToolBar(), BorderLayout.NORTH);  
        
        // Add the Graph as Center Component
        add(new JScrollPane(graph), BorderLayout.CENTER);
        messageTextArea = new JTextArea();
        messageTextArea.setRows(5);
        add(new JScrollPane(messageTextArea) , BorderLayout.SOUTH);
        //setEnabled(false);
    }

    // Insert a new Vertex at point
    public void insert(Point2D point, String actionType) {
        stepNum++;    
        //URL jgraphUrl = Editor.class.getClassLoader().getResource("gif\\Step.jpg");    
        //ImageIcon iIcon = new ImageIcon(jgraphUrl);    
        // Construct Vertex with no Label
        ImageIcon imageIcon = getImageIconByActionType(actionType);
        ImageCell vertex = new ImageCell();
        GPUserObject userObject =new GPUserObject();
        
        userObject.setValue(NEW_STEP);
        userObject.putProperty("STEPTYPE",actionType);
        vertex.setUserObject(userObject);
        // Add one Floating Port
        vertex.add(new DefaultPort());
        // Snap the Point to the Grid
        point = graph.snap(point);
        // Default Size for the new Vertex
        Dimension2D size = new Dimension(100,30);
        // Create a Map that holds the attributes for the Vertex
        Map map = new Hashtable();
        // Add a Bounds Attribute to the Map
        GraphConstants.setBounds(map, new Rectangle2D.Double(
                point.getX(), point.getY(), size.getWidth(), size.getHeight()));
        //GraphConstants.setBackground( mpa,StepColor );
        // Add a Border Color Attribute to the Map
        //GraphConstants.setBorderColor(map, Color.black);
        // Add a White Background
        //GraphConstants.setBackground(map, selectedColor);
        GraphConstants.setEditable(map, false);
        // Make Vertex Opaque
        GraphConstants.setOpaque(map, false);        
        // Set Icon    
        GraphConstants.setIcon(map,imageIcon);
        // Construct a Map from cells to Maps (for insert)
        
        //GraphConstants.setForeground( map,Color.WHITE );
        //GraphConstants.setIcon(map,new ImageIcon(getURLByString("gif/Save.gif")));
        //GraphConstants.setHorizontalTextPosition(map, JLabel.TOP);
        Hashtable attributes = new Hashtable();
        // Associate the Vertex with its Attributes
        attributes.put(vertex, map);
        // Insert the Vertex and its Attributes (can also use model)
        graph.getGraphLayoutCache().insert(
            new Object[] { vertex },
            attributes,
            null,
            null,
            null);
    }
//  Insert a new Vertex at point
    public DefaultPort insertNewStep(Point2D point, WorkflowStep workflowStep) {
        stepNum++;    
        //URL jgraphUrl = Editor.class.getClassLoader().getResource("gif\\Step.jpg");    
        //ImageIcon iIcon = new ImageIcon(jgraphUrl);    
        // Construct Vertex with no Label
        actionType = workflowStep.getActionType();
        ImageIcon imageIcon  = getImageIconByActionType(actionType);
        ImageCell vertex = new ImageCell();
        GPUserObject userObject =new GPUserObject();
        userObject.putProperty("ID",workflowStep.getID().toString());
        if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(workflowStep.getActionType())){
          userObject.putProperty("STEPTYPE",workflowStep.getActionType()+workflowStep.getActionID());
        }else{
          userObject.putProperty("STEPTYPE",workflowStep.getActionType());
        }
        String showValue = workflowStep.getStepSeq().toString()+"."+workflowStep.getStepName();
        userObject.setValue(showValue);
        vertex.setUserObject(userObject);
        // Add one Floating Port
        DefaultPort defaultPort = new DefaultPort();
        vertex.add(defaultPort);
        // Snap the Point to the Grid
        point = graph.snap(point);
        // Default Size for the new Vertex
        Dimension size = new Dimension(100,30);
        // Create a Map that holds the attributes for the Vertex
        Map map = new Hashtable();
        // Add a Bounds Attribute to the Map
        GraphConstants.setBounds(map, new Rectangle2D.Double(
                point.getX(), point.getY(), size.getWidth(), size.getHeight()));
        //GraphConstants.setBackground( mpa,StepColor );
        // Add a Border Color Attribute to the Map
        //GraphConstants.setBorderColor(map, Color.black);
        // Add a White Background
        //GraphConstants.setBackground(map, STEP_TODO_COLOR);
        GraphConstants.setEditable(map, false);
        // Make Vertex Opaque
        GraphConstants.setOpaque(map, false);
        GraphConstants.setIcon(map,imageIcon);
        // Set Icon    
        //GraphConstants.setIcon(map,iIcon);
        // Construct a Map from cells to Maps (for insert)
        
        //GraphConstants.setForeground( map,Color.WHITE );
        
        Hashtable attributes = new Hashtable();
        // Associate the Vertex with its Attributes
        attributes.put(vertex, map);
        // Insert the Vertex and its Attributes (can also use model)
        graph.getGraphLayoutCache().insert(
            new Object[] { vertex },
            attributes,
            null,
            null,
            null);
        return defaultPort;
    }
//  Hook for subclassers
    protected Map createCellAttributes(Point2D point) {
        Map map = new Hashtable();
        // Snap the Point to the Grid
        point = graph.snap((Point2D) point.clone());
        // Add a Bounds Attribute to the Map
        GraphConstants.setBounds(map, new Rectangle2D.Double(
            point.getX(), point.getY(), 0, 0));
        // Make sure the cell is resized on insert
        GraphConstants.setResize(map, true);
        // Add a nice looking gradient background
        GraphConstants.setGradientColor(map, Color.blue);
        // Add a Border Color Attribute to the Map
        GraphConstants.setBorderColor(map, Color.black);
        // Add a White Background
        GraphConstants.setBackground(map, Color.white);
        // Make Vertex Opaque
        GraphConstants.setOpaque(map, true);
        return map;
    }

    // Insert a new Edge between source and target
    public void connect(Port source, Port target) {
      DefaultGraphCell cell = (DefaultGraphCell)((DefaultPort)source).getParent();
      GPUserObject userObject;
      GPUserObject connectType = new GPUserObject();
      DefaultEdge edge = new DefaultEdge();
      if(cell.getUserObject() instanceof GPUserObject){
        userObject = (GPUserObject)cell.getUserObject();
      } else {
        userObject =new GPUserObject();
      }
      String parentActionType = (String)userObject.getProperty("STEPTYPE");
      String actionID;
      if(WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(parentActionType)){
        FormDriveConnectionWindow formDriveConnectionWindow = new FormDriveConnectionWindow(null, "Form Value Driven", true);
        formDriveConnectionWindow.setBounds(Editor.this.getX(),Editor.this.getY(),500,400);
        formDriveConnectionWindow.setLocationRelativeTo(Editor.this);
        formDriveConnectionWindow.setEdge(edge);
        formDriveConnectionWindow.initData(workflowRecordID.toString(),httpOperation,hostURL,Editor.this);
        formDriveConnectionWindow.show();
        
        connectType =(GPUserObject)edge.getUserObject();
        String routeName = userObject.toString();
        if(Utility.isEmpty(routeName)){
          //String equation = userObject.getProperty("EQUATION").toString();
          //connectType.putProperty("TYPE","D_"+routeName+"#"+equation);
          //connectType.setValue(routeName);
          undo();
          redo();
          return;
        }
      } else if(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(parentActionType)){
        CustomConnectionWindow customConnectionWindow = new CustomConnectionWindow(null, AppletResource.lableArr[147], true);
        customConnectionWindow.setBounds(Editor.this.getX(),Editor.this.getY(),300,150);
        customConnectionWindow.setLocationRelativeTo(Editor.this);
        customConnectionWindow.setEdge(edge);
        customConnectionWindow.show();
        Object routeName = edge.getUserObject();
        if(!Utility.isEmpty(routeName)){
          connectType.putProperty("TYPE","U"+AppletConstant.SPLITCHAR+routeName.toString());
          connectType.setValue(routeName.toString());
          //GraphConstants.setValue(map,routeName.toString());
        } else {
          undo();
          redo();
          return;
        }
      } else if(!WorkflowStep.ACTION_TYPE_TASK_TO_DO.equals(parentActionType)&&!WorkflowStep.ACTION_TYPE_SUBMIT.equals(parentActionType)){
        if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(parentActionType)){
          AppletResource.lableArr[299]=cell.toString();
          String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{1,299});
          outputMessage(message, false);
          undo();
          redo();
          return;
        }
        RouteWindow routeWindow = new RouteWindow(null, AppletResource.lableArr[161], true);
        routeWindow.setBounds(Editor.this.getX(),Editor.this.getY(),350,200);
        routeWindow.setLocationRelativeTo(Editor.this);
        routeWindow.setEditor(this);
        routeWindow.setEdge(edge);
        routeWindow.setActionType(parentActionType);        
        routeWindow.initData();
        routeWindow.show();
        Object routeName = edge.getUserObject();
        if(!Utility.isEmpty(routeName)){
          //connectType.putProperty("TYPE","U_"+routeName.toString());
          //connectType.setValue(routeName.toString());
          //GraphConstants.setValue(map,routeName.toString());
        } else {
          undo();
          redo();
          return;
        }
      } else {
        connectType.putProperty("TYPE",WorkflowStep.PARENT_TYPE_SINGLE);
        connectType.setValue(AppletResource.lableArr[86]);
        edge.setUserObject(connectType);
      }
      connectType=(GPUserObject)edge.getUserObject();
      //connectType.putProperty("TYPE",selectedConnectType);
      //connectType.setValue(selectedConnectName);
      
      ObjectInputStream inputFromServlet = null;
      //String stepType = (String)userObject.getProperty("STEPTYPE");
      //String actionID;
      
      // Connections that will be inserted into the Model
        ConnectionSet cs = new ConnectionSet();
        // Construct Edge with no label
        //edge.setUserObject(connectType);
        // Create Connection between source and target using edge
        cs.connect(edge, source, target);
        // Create a Map thath holds the attributes for the edge
        Map map = new Hashtable();
        // Add a Line End Attribute
        GraphConstants.setValue(map,connectType.toString());
        GraphConstants.setLineColor(map,LINE_TODO_COLOR);
        GraphConstants.setRouting(map,FormatRoutingParallel.parallelEdgeRouter);
        GraphConstants.setLineStyle(map,GraphConstants.STYLE_ORTHOGONAL);
        GraphConstants.setLineEnd(map,GraphConstants.ARROW_CLASSIC);
        GraphConstants.setEndFill(map, true);
        GraphConstants.setEditable(map,false);
        //GraphConstants.setLabelAlongEdge(map, true);
        
        /*if(CONNECTNAME_CUSTOM.equals(selectedConnectName)){
          CustomConnectionWindow customConnectionWindow = new CustomConnectionWindow(null, AppletResource.lableArr[147], true);
          customConnectionWindow.setBounds(Editor.this.getX(),Editor.this.getY(),300,150);
          customConnectionWindow.setLocationRelativeTo(Editor.this);
          customConnectionWindow.setEdge(edge);
          customConnectionWindow.show();
          Object routeName = edge.getUserObject();
          if(!Utility.isEmpty(routeName)){
            connectType.putProperty("TYPE","U_"+routeName.toString());
            connectType.setValue(routeName.toString());
            //GraphConstants.setValue(map,routeName.toString());
          } else {
            undo();
            redo();
            return;
          }
          
        } else if(CONNECTNAME_FORM_VALUE_DRIVEN.equals(selectedConnectName)){
          FormDriveConnectionWindow formDriveConnectionWindow = new FormDriveConnectionWindow(null, "Custom Route", true);
          formDriveConnectionWindow.setBounds(Editor.this.getX(),Editor.this.getY(),500,400);
          formDriveConnectionWindow.setLocationRelativeTo(Editor.this);
          formDriveConnectionWindow.setEdge(edge);
          formDriveConnectionWindow.initData(workflowRecordID.toString(),httpOperation,hostURL,Editor.this);
          formDriveConnectionWindow.show();
          
          connectType =(GPUserObject)edge.getUserObject();
          String routeName = userObject.toString();
          if(Utility.isEmpty(routeName)){
            //String equation = userObject.getProperty("EQUATION").toString();
            //connectType.putProperty("TYPE","D_"+routeName+"#"+equation);
            //connectType.setValue(routeName);
            undo();
            redo();
            return;
          }
          GraphConstants.setValue(map,edge.getUserObject().toString());
        } else if(CONNECTNAME_AUTO_TASK.equals(selectedConnectName)){
          if(!createAutoTaskConnectionType(source, edge)){
            undo();
            redo();
            return;
          }
          Object routeName = edge.getUserObject();
          if(!Utility.isEmpty(routeName)){
            String type = WindowUtilities.splitString(routeName.toString(),"_")[0];
            connectType.putProperty("TYPE",type);
            connectType.setValue(WindowUtilities.splitString(routeName.toString(),"_")[1]);
            GraphConstants.setValue(map,WindowUtilities.splitString(routeName.toString(),"_")[1]);
          } else {
            undo();
            redo();
            return;
          }
        } else {
          connectType.putProperty("TYPE",selectedConnectType);
          GraphConstants.setValue(map,selectedConnectName);
        }*/
        // Construct a Map from cells to Maps (for insert)
        Hashtable attributes = new Hashtable();
        // Associate the Edge with its Attributes
        attributes.put(edge, map);
        // Insert the Edge and its Attributes
        graph.getGraphLayoutCache().insert(
            new Object[] { edge },
            attributes,
            cs,
            null,
            null);
        edge.setUserObject(connectType);
    }
    
//  Insert a new Edge between source and target
    public void initConnect(Port source, Port target, String parentType) {      
      GPUserObject connectType = new GPUserObject();
      connectType.putProperty("TYPE", parentType);
      connectType.setValue(selectedConnectName);
      // Connections that will be inserted into the Model
        ConnectionSet cs = new ConnectionSet();
        // Construct Edge with no label
        DefaultEdge edge = new DefaultEdge(); 
        
        // Create Connection between source and target using edge
        cs.connect(edge, source, target);
        // Create a Map thath holds the attributes for the edge
        Map map = new Hashtable();
        // Add a Line End Attribute
        GraphConstants.setLineColor(map,LINE_TODO_COLOR);
        GraphConstants.setRouting(map,FormatRoutingParallel.parallelEdgeRouter);
        GraphConstants.setLineStyle(map,GraphConstants.STYLE_ORTHOGONAL);
        
        GraphConstants.setLineEnd(map,GraphConstants.ARROW_CLASSIC);
        GraphConstants.setEndFill(map, true);
        GraphConstants.setEditable(map,false);
        GraphConstants.setValue(map,selectedConnectName);        
        // Construct a Map from cells to Maps (for insert)
        Hashtable attributes = new Hashtable();
        // Associate the Edge with its Attributes
        attributes.put(edge, map);
        // Insert the Edge and its Attributes
        graph.getGraphLayoutCache().insert(
            new Object[] { edge },
            attributes,
            cs,
            null,
            null);
        edge.setUserObject(connectType);
    }


    // Create a Group that Contains the Cells
    public void group(Object[] cells) {
        // Order Cells by View Layering
        //cells = graph.getGraphLayoutCache().order(cells);
        // If Any Cells in View
        if (cells != null && cells.length > 0) {
            // Create Group Cell
            int count = getCellCount(graph);
            DefaultGraphCell group =
                new DefaultGraphCell(new Integer(count - 1));
            // Create Change Information
            ParentMap map = new ParentMap();
            // Insert Child Parent Entries
            for (int i = 0; i < cells.length; i++)
                map.addEntry(cells[i], group);
            // Insert into model
            graph.getGraphLayoutCache().insert(
                new Object[] { group },
                null,
                null,
                map,
                null);
        }
    }

    // Returns the total number of cells in a graph
    protected int getCellCount(JGraph graph) {
        Object[] cells = graph.getDescendants(graph.getRoots());
        return cells.length;
    }

    // Ungroup the Groups in Cells and Select the Children
    public void ungroup(Object[] cells) {
        // If any Cells
        if (cells != null && cells.length > 0) {
            // List that Holds the Groups
            ArrayList groups = new ArrayList();
            // List that Holds the Children
            ArrayList children = new ArrayList();
            // Loop Cells
            for (int i = 0; i < cells.length; i++) {
                // If Cell is a Group
                if (isGroup(cells[i])) {
                    // Add to List of Groups
                    groups.add(cells[i]);
                    // Loop Children of Cell
                    for (int j = 0;
                        j < graph.getModel().getChildCount(cells[i]);
                        j++) {
                        // Get Child from Model
                        Object child = graph.getModel().getChild(cells[i], j);
                        // If Not Port
                        if (!(child instanceof Port))
                            // Add to Children List
                            children.add(child);
                    }
                }
            }
            // Remove Groups from Model (Without Children)
            graph.getGraphLayoutCache().remove(groups.toArray());
            // Select Children
            graph.setSelectionCells(children.toArray());
        }
    }

    // Determines if a Cell is a Group
    public boolean isGroup(Object cell) {
        // Map the Cell to its View
        CellView view = graph.getGraphLayoutCache().getMapping(cell, false);
        if (view != null)
            return !view.isLeaf();
        return false;
    }

    // Brings the Specified Cells to Front
    public void toFront(Object[] c) {
        graph.getGraphLayoutCache().toFront(c);
    }

    // Sends the Specified Cells to Back
    public void toBack(Object[] c) {
        graph.getGraphLayoutCache().toBack(c);
    }

    // Undo the last Change to the Model or the View
    public void undo() {
        try {
            undoManager.undo(graph.getGraphLayoutCache());
        } catch (Exception ex) {
            //System.err.println(ex);
        } finally {
            updateHistoryButtons();
        }
    }

    // Redo the last Change to the Model or the View
    public void redo() {
        try {
            undoManager.redo(graph.getGraphLayoutCache());
        } catch (Exception ex) {
            System.err.println(ex);
        } finally {
            updateHistoryButtons();
        }
    }

    // Update Undo/Redo Button State based on Undo Manager
    protected void updateHistoryButtons() {
        // The View Argument Defines the Context
      toggleButtons[10].setEnabled(undoManager.canUndo(graph.getGraphLayoutCache()));
      toggleButtons[11].setEnabled(undoManager.canRedo(graph.getGraphLayoutCache()));
    }

    //
    // Listeners
    //

    // From GraphSelectionListener Interface
    public void valueChanged(GraphSelectionEvent e) {
        // Group Button only Enabled if more than One Cell Selected
      toggleButtons[18].setEnabled(graph.getSelectionCount() > 1);
        // Update Button States based on Current Selection
        boolean enabled = !graph.isSelectionEmpty();
        toggleButtons[15].setEnabled(enabled);
        toggleButtons[19].setEnabled(enabled);
        toggleButtons[20].setEnabled(enabled);
        toggleButtons[21].setEnabled(enabled);
        toggleButtons[12].setEnabled(enabled);
        toggleButtons[13].setEnabled(enabled);
    }
    protected ImageIcon getImageIconByActionType(String actionType){
      URL url = getURLByString("gif/step_todo.gif");
      if(WorkflowStep.ACTION_TYPE_TASK_TO_DO.equals(actionType)){
        url = getURLByString("gif/step_todo.gif");
      } else if(WorkflowStep.ACTION_TYPE_BOOLEAN.equals(actionType)) {
        url = getURLByString("gif/step_bool.gif");
      } else if(WorkflowStep.ACTION_TYPE_APPROVAL.equals(actionType)){
        url = getURLByString("gif/step_bool.gif");
      } else if(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(actionType)){
        url = getURLByString("gif/step_userdefined.gif");
      } else if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(actionType)){
        url = getURLByString("gif/step_auto.gif");
      } else if(WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(actionType)){
        url = getURLByString("gif/step_driven.gif");
      } else if(WorkflowStep.ACTION_TYPE_SUBMIT.equals(actionType)){
        url = getURLByString("gif/step_startend.gif");
      } else if(WorkflowStep.ACTION_TYPE_END.equals(actionType)){
        url = getURLByString("gif/step_startend.gif");
      }
      return new ImageIcon(url);
    }

    //
    // KeyListener for Delete KeyStroke
    //
    public void keyReleased(KeyEvent e) {
    }
    public void keyTyped(KeyEvent e) {
    }
    public void keyPressed(KeyEvent e) {
        // Listen for Delete Key Press
        if (e.getKeyCode() == KeyEvent.VK_DELETE)
            // Execute Remove Action on Delete Key Press
          actionListeners[15].actionPerformed(null);
    }

    //
    // Custom Graph
    //

    // Defines a Graph that uses the Shift-Button (Instead of the Right
    // Mouse Button, which is Default) to add/remove point to/from an edge.
    public class MyGraph extends GPGraph {

  public static final String REVISION = "$Revision: 1.20 $";


        // Construct the Graph using the Model as its Data Source
        public MyGraph(GraphModel model) {
            super(model);
            // Use a Custom Marquee Handler
            setMarqueeHandler(new MyMarqueeHandler());
            // Tell the Graph to Select new Cells upon Insertion
            //setSelectNewCells(true);
            // Make Ports Visible by Default
            setPortsVisible(Editor.this.ispending);
            // Use the Grid (but don't make it Visible)
            setGridEnabled(true);
            // Set the Grid Size to 10 Pixel
            setGridSize(6);
            // Set the Tolerance to 2 Pixel
            setTolerance(2);
        }

        // Override Superclass Method to Return Custom EdgeView
        protected EdgeView createEdgeView(Edge e, CellMapper cm) {
            // Return Custom EdgeView
            return new EdgeView(e) {
                // Override Superclass Method
                public boolean isAddPointEvent(MouseEvent event) {
                    // Points are Added using Shift-Click
                    return event.isShiftDown();
                }
                // Override Superclass Method
                public boolean isRemovePointEvent(MouseEvent event) {
                    // Points are Removed using Shift-Click
                    return event.isShiftDown();
                }
            };
        }
    }

    //
    // Custom Model
    //

    // A Custom Model that does not allow Self-References
    public class MyModel extends DefaultGraphModel {

  public static final String REVISION = "$Revision: 1.20 $";

        // Override Superclass Method
        public boolean acceptsSource(Object edge, Object port) {
            // Source only Valid if not Equal Target
            return (((Edge) edge).getTarget() != port);
        }
        // Override Superclass Method
        public boolean acceptsTarget(Object edge, Object port) {
            // Target only Valid if not Equal Source
            return (((Edge) edge).getSource() != port);
        }
    }

    //
    // Custom MarqueeHandler

    // MarqueeHandler that Connects Vertices and Displays PopupMenus
    public class MyMarqueeHandler extends BasicMarqueeHandler {

  public static final String REVISION = "$Revision: 1.20 $";


        // Holds the Start and the Current Point
        protected Point2D start, current;

        // Holds the First and the Current Port
        protected PortView port, firstPort;

        // Override to Gain Control (for PopupMenu and ConnectMode)
        public boolean isForceMarqueeEvent(MouseEvent e) {
            // If Right Mouse Button we want to Display the PopupMenu
            if (SwingUtilities.isRightMouseButton(e))
                // Return Immediately
                return true;
            // Find and Remember Port
            Point2D loc = graph.fromScreen(e.getPoint());
            // Find Cell in Model Coordinates
            Object cell = graph.getFirstCellForLocation(e.getX(), e.getY());
              if(cell instanceof DefaultEdge){
                DefaultEdge defaultEdge  = (DefaultEdge)cell;
                GPUserObject userObject = (GPUserObject)defaultEdge.getUserObject();
                String routeType = userObject.getProperty("TYPE").toString();
                if(routeType.length()>1&&CONNECTNAME_FORM_VALUE_DRIVEN.equals(routeType.substring(0,2))){
                  String equationInfo = WindowUtilities.splitString(routeType,"#")[1];
                  String[] equation = WindowUtilities.splitString(equationInfo,";");
                  if("Y".equals(equation[1])){
                    outputMessage(equation[0]+" -- [Default Route]",false);
                  } else {
                    outputMessage(equation[0]+" -- "+equation[5],false);
                  }
                  
                }
                
            }
            port = getSourcePortAt(e.getPoint());
            // If Port Found and in ConnectMode (=Ports Visible)
            if (port != null && graph.isPortsVisible())
                return true;
            // Else Call Superclass
            return super.isForceMarqueeEvent(e);
        }

        // Display PopupMenu or Remember Start Location and First Port
        public void mousePressed(final MouseEvent e) {
            if (!getEnabled())
                return ;
            // If Right Mouse Button
            if (SwingUtilities.isRightMouseButton(e)) {
                // Scale From Screen to Model
                Point2D loc = graph.fromScreen(e.getPoint());
                // Find Cell in Model Coordinates
                Object cell = graph.getFirstCellForLocation(e.getX(), e.getY());
                  if(cell instanceof DefaultGraphCell&&!(cell instanceof DefaultEdge)){
                  // Create PopupMenu for the Cell
                  JPopupMenu menu = createPopupMenu(e.getPoint(), cell);
                  // Display PopupMenu
                  menu.show(graph, e.getX(), e.getY());
                }

                // Else if in ConnectMode and Remembered Port is Valid
            }else {
              if(selectedType == Editor.SELECTED_TYPE_STEP_OFFSET
                  
                          || selectedType == Editor.SELECTED_TYPE_STEP_SPLIT
                          || selectedType == Editor.SELECTED_TYPE_STEP_TODO){                
                insert(e.getPoint(),actionType);
                selectedType = SELECTED_NONE ;
                selectedColor = BLANK_COLOR;
                graph.setPortsVisible(false);                
                toggleButtons[0].setSelected(true);
              } else if (
                port != null && !e.isConsumed() && graph.isPortsVisible()) {
                // Remember Start Location
                start = graph.toScreen(port.getLocation(null));
                // Remember First Port
                firstPort = port;
                // Consume Event
                e.consume();
              } else
                    return;
            }
              
                // Call Superclass
                //super.mousePressed(e);
        }

        // Find Port under Mouse and Repaint Connector
        public void mouseDragged(MouseEvent e) {
            // If remembered Start Point is Valid
            if (start != null && !e.isConsumed()) {
                // Fetch Graphics from Graph
                Graphics g = graph.getGraphics();
                // Xor-Paint the old Connector (Hide old Connector)
                paintConnector(Color.black, graph.getBackground(), g);
                // Reset Remembered Port
                port = getTargetPortAt(e.getPoint());
                // If Port was found then Point to Port Location
                if (port != null)
                  current = graph.toScreen(port.getLocation(null));
                // Else If no Port was found then Point to Mouse Location
                else
                  current = graph.snap(e.getPoint());
                // Xor-Paint the new Connector
                paintConnector(graph.getBackground(), Color.black, g);
                // Consume Event
                e.consume();
            }
            // Call Superclass
            super.mouseDragged(e);
        }

        public PortView getSourcePortAt(Point2D point) {
            // Scale from Screen to Model
            Point2D tmp = graph.fromScreen(point);
            // Find a Port View in Model Coordinates and Remember
            return graph.getPortViewAt(tmp.getX(), tmp.getY());
        }

        // Find a Cell at point and Return its first Port as a PortView
        protected PortView getTargetPortAt(Point point) {
            // Find Cell at point (No scaling needed here)
            Object cell = graph.getFirstCellForLocation(point.x, point.y);
            // Loop Children to find PortView
            for (int i = 0; i < graph.getModel().getChildCount(cell); i++) {
                // Get Child from Model
                Object tmp = graph.getModel().getChild(cell, i);
                // Get View for Child using the Graph's View as a Cell Mapper
                tmp = graph.getGraphLayoutCache().getMapping(tmp, false);
                // If Child View is a Port View and not equal to First Port
                if (tmp instanceof PortView && tmp != firstPort)
                    // Return as PortView
                    return (PortView) tmp;
            }
            // No Port View found
            return getSourcePortAt(point);
        }

        // Connect the First Port and the Current Port in the Graph or Repaint
        public void mouseReleased(MouseEvent e) {
            // If Valid Event, Current and First Port
            if (e != null
                && !e.isConsumed()
                && port != null
                && firstPort != null
                && firstPort != port) {
                // Then Establish Connection
                connect((Port) firstPort.getCell(), (Port) port.getCell());
                // Consume Event
                e.consume();
                // Else Repaint the Graph
            } else
                graph.repaint();
            // Reset Global Vars
            firstPort = port = null;
            start = current = null;
            // Call Superclass
            super.mouseReleased(e);
        }

        // Show Special Cursor if Over Port
        public void mouseMoved(MouseEvent e) {
            // Check Mode and Find Port
            if (e != null
                && getSourcePortAt(e.getPoint()) != null
                && !e.isConsumed()
                && graph.isPortsVisible()) {
                // Set Cusor on Graph (Automatically Reset)
                graph.setCursor(new Cursor(Cursor.HAND_CURSOR));
                // Consume Event
                e.consume();
            }
            // Call Superclass
            super.mouseReleased(e);
        }

        // Use Xor-Mode on Graphics to Paint Connector
        protected void paintConnector(Color fg, Color bg, Graphics g) {
            // Set Foreground
            g.setColor(fg);
            // Set Xor-Mode Color
            g.setXORMode(bg);
            // Highlight the Current Port
            //paintPort(graph.getGraphics());
            // If Valid First Port, Start and Current Point
            if (firstPort != null && start != null && current != null)
                // Then Draw A Line From Start to Current Point
                g.drawLine((int)start.getX(), (int)start.getY(), (int)current.getX(), (int)current.getY());
        }

        // Use the Preview Flag to Draw a Highlighted Port
        protected void paintPort(Graphics g) {
            // If Current Port is Valid
            if (port != null) {
                // If Not Floating Port...
                boolean o =
                    (GraphConstants.getOffset(port.getAttributes()) != null);
                // ...Then use Parent's Bounds
                Rectangle2D r =
                    (o) ? port.getBounds() : port.getParentView().getBounds();
                // Scale from Model to Screen
                r = graph.toScreen(r);
                // Add Space For the Highlight Border
                r.setRect(new Rectangle2D.Double(r.getX() - 3, r.getY() - 3, r.getWidth() + 6, r.getHeight() + 6));
                // Paint Port in Preview (=Highlight) Mode
                graph.getUI().paintCell(g, port, r, true);
            }
        }

    } // End of Editor.MyMarqueeHandler

    //
    //
    //

    //
    // PopupMenu and ToolBar
    //

    //
    //
    //

    //
    // PopupMenu
    //
    public JPopupMenu createPopupMenu(final Point pt, final Object cell) {        
        JPopupMenu menu = new JPopupMenu();
        if (cell != null) {
            // Edit
            menu.add(new AbstractAction(AppletResource.lableArr[30]) {
                public void actionPerformed(ActionEvent e) {
                    //((DefaultGraphCell)cell).getUserObject() ;
                    
                    //graph.startEditingAtCell(cell);
                    //StepInformationWindow workflowStepInfoWindow = new StepInformationWindow();
                    //workflowStepInfoWindow.setWorkflowStepRecord((WorkflowStepRecord)((DefaultGraphCell)cell).getUserObject());
                    StepInformationWindow workflowStepInfoWindow = 
                        new StepInformationWindow(((DefaultGraphCell)cell).getUserObject(),workflowRecordID.toString(),  hostURL, httpOperation);
                    workflowStepInfoWindow.setBounds(Editor.this.getX(),Editor.this.getY(),600,400);
                    workflowStepInfoWindow.setLocationRelativeTo(Editor.this);
                    workflowStepInfoWindow.setCell(cell);
                    workflowStepInfoWindow.setEditor(Editor.this);
                    workflowStepInfoWindow.setModal(true);
                    workflowStepInfoWindow.show();                    
                    //CellView view = graph.getGraphLayoutCache().getMapping(cell, false);                    
                    //view.update();
                    graph.getGraphLayoutCache().reload();
                    graph.clearSelection();

                    
                }
            });
        }
        // Remove
        if (!graph.isSelectionEmpty()) {
            menu.addSeparator();
            menu.add(new AbstractAction(AppletResource.lableArr[31]) {
                public void actionPerformed(ActionEvent e) {
                  actionListeners[15].actionPerformed(e);
                }
            });
        }
        menu.addSeparator();
/*        
        // Insert
        menu.add(new AbstractAction("Insert") {
            public void actionPerformed(ActionEvent ev) {
                insert(pt);
            }
        });
*/        
        return menu;
    }

    //
    // ToolBar
    //
    public JToolBar createToolBar() {
        JToolBar toolbar = new JToolBar();
        toolbar.setFloatable(false);
        Insets insets = new Insets(-2,-2,-2,-2);

        /*URL saveUrl = getURLByString("gif/Save.gif");        
        ImageIcon saveIcon = new ImageIcon(saveUrl);
        
        
        saveButton = new JButton(saveIcon);
        saveButton.setMargin(insets);
        saveButton.setToolTipText(AppletResource.lableArr[24]);
        saveButton.addActionListener(new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
              //checkAllStepRecord();
              saveChartToServer();
              
                //saveEditor();
            }
        });                
        
        toolbar.add(saveButton);
        
        URL closeUrl = getURLByString("gif/Close.gif");
        ImageIcon closeIcon = new ImageIcon(closeUrl);
        
        
        closeButton = new JButton(closeIcon);
        closeButton.setMargin(insets);
        closeButton.setToolTipText(AppletResource.lableArr[25]);
        closeButton.addActionListener(new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                //closeEditor();
            }
        });
        
        toolbar.add(closeButton);*/
        
/*        
        toolbar.add(new AbstractAction("Close", closeIcon) {
            public void actionPerformed(ActionEvent e) {
                closeEditor();
            }
        });   
*/        
        
        toolbar.addSeparator();        

        URL[] urls = new URL[]{
            getURLByString("gif/Save.gif"),//0
            getURLByString("gif/Close.gif"),
            getURLByString("gif/NoSelect.gif"),                
            getURLByString("gif/IconToDo.gif"),
            getURLByString("gif/IconBoolean.gif"),
            getURLByString("gif/IconApproval.gif"),
            getURLByString("gif/IconUserDefine.gif"),
            getURLByString("gif/IconFormValueDriven.gif"),
            getURLByString("gif/IconAutoTask.gif"),
            //getURLByString("gif/StepToDo.gif"),
            //getURLByString("gif/StepToDo.gif"),
            getURLByString("gif/ConnectToDo.gif"),//5
            /*getURLByString("gif/ConnectYes.gif"),
            getURLByString("gif/ConnectNot.gif"),
            getURLByString("gif/ConnectApprove.gif"),
            getURLByString("gif/ConnectReject.gif"),
            getURLByString("gif/ConnectCustom.gif"),//10
            getURLByString("gif/ConnectFormValueDriven.gif"),
            getURLByString("gif/ConnectAutoTask.gif"),*/
            getURLByString("gif/undo.gif"),
            getURLByString("gif/redo.gif"),
            getURLByString("gif/copy.gif"),//15
            getURLByString("gif/paste.gif"),
            getURLByString("gif/cut.gif"),
            getURLByString("gif/delete.gif"),
            getURLByString("gif/zoomin.gif"),
            getURLByString("gif/zoomout.gif"),//20
            getURLByString("gif/group.gif"),
            getURLByString("gif/ungroup.gif"),
            getURLByString("gif/tofront.gif"),
            getURLByString("gif/toback.gif"),
            getURLByString("gif/Layout.gif"),//25
        }; 
        ImageIcon[] imageIcons = new ImageIcon[urls.length];
        for(int i=0;i<urls.length;i++){
          imageIcons[i]=new ImageIcon(urls[i]);
        }
        String[] toolbarTitle = {
            AppletResource.lableArr[24],//0
            AppletResource.lableArr[25],
            AppletResource.lableArr[32],
            AppletResource.lableArr[152],
            AppletResource.lableArr[154],
            AppletResource.lableArr[151],
            AppletResource.lableArr[156],
            AppletResource.lableArr[155],
            "Auto Task",
            AppletResource.lableArr[34],
            //AppletResource.lableArr[34],//5
            //AppletResource.lableArr[35],
            //AppletResource.lableArr[36],
            //AppletResource.lableArr[37],
            //AppletResource.lableArr[38],
            //AppletResource.lableArr[39],//10
            //AppletResource.lableArr[40],
            //AppletResource.lableArr[41],
            AppletResource.lableArr[45],
            AppletResource.lableArr[46],
            AppletResource.lableArr[47],//15
            AppletResource.lableArr[48],
            AppletResource.lableArr[49],
            AppletResource.lableArr[50],
            AppletResource.lableArr[51],
            AppletResource.lableArr[52],//20
            AppletResource.lableArr[53],
            AppletResource.lableArr[54],
            AppletResource.lableArr[55],
            AppletResource.lableArr[56],
            AppletResource.lableArr[57],//25
        };
        
        
        actionListeners = new ActionListener[]{ 
            //open
            new AbstractAction() {
              public void actionPerformed(ActionEvent e) {
                //checkAllStepRecord();
                saveChartToServer();
                
                  //saveEditor();
              }
            },
            //close
            new AbstractAction() {
              public void actionPerformed(ActionEvent e) {
                  //closeEditor();
              }
           },
            //NoSelect                
            new ActionListener(){
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_NONE ;
                        selectedColor = BLANK_COLOR;
                        graph.setPortsVisible(false);
                    }
                },
                //StepToDo
            new ActionListener(){
            public void actionPerformed(ActionEvent e){
                    selectedType = SELECTED_TYPE_STEP_TODO;
                    selectedColor = STEP_TODO_COLOR ;            
                    selectedTypeName = STEP_TODO;
                    actionType=WorkflowStep.ACTION_TYPE_TASK_TO_DO;
                }            
            },
            //              StepBoolean
            new ActionListener(){
                 public void actionPerformed(ActionEvent e){
                         selectedType = SELECTED_TYPE_STEP_TODO;
                         selectedColor = STEP_TODO_COLOR ;            
                         selectedTypeName = STEP_TODO;
                         actionType=WorkflowStep.ACTION_TYPE_BOOLEAN;
                     }            
                 },
                 //                   StepApproval
           new ActionListener(){
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_STEP_TODO;
                        selectedColor = STEP_TODO_COLOR ;            
                        selectedTypeName = STEP_TODO;
                        actionType=WorkflowStep.ACTION_TYPE_APPROVAL;
                    }            
                },
                //StepUserDefinded
            new ActionListener(){
                 public void actionPerformed(ActionEvent e){
                         selectedType = SELECTED_TYPE_STEP_TODO;
                         selectedColor = STEP_TODO_COLOR ;            
                         selectedTypeName = STEP_TODO;
                         actionType=WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK;
                     }            
                 },
                 //StepFromValueDrinven
           new ActionListener(){
             public void actionPerformed(ActionEvent e){
                     selectedType = SELECTED_TYPE_STEP_TODO;
                     selectedColor = STEP_TODO_COLOR ;            
                     selectedTypeName = STEP_TODO;
                     actionType=WorkflowStep.ACTION_TYPE_FORM_DRIVEN;
                 }            
             },
             //StepAuto
           new ActionListener(){
                                   public void actionPerformed(ActionEvent e){
                                           selectedType = SELECTED_TYPE_STEP_TODO;
                                           selectedColor = STEP_TODO_COLOR ;            
                                           selectedTypeName = STEP_TODO;
                                           actionType=WorkflowStep.ACTION_TYPE_SYSTEM_AUTO;
                                       }            
                                   },
          //StepStart 
          /*new ActionListener(){
             public void actionPerformed(ActionEvent e){
                     selectedType = SELECTED_TYPE_STEP_TODO;
                     selectedColor = STEP_TODO_COLOR ;            
                     selectedTypeName = STEP_TODO;
                     actionType=WorkflowStep.ACTION_TYPE_SUBMIT;
                 }            
             },
//           StepEnd 
             new ActionListener(){
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_STEP_TODO;
                        selectedColor = STEP_TODO_COLOR ;            
                        selectedTypeName = STEP_TODO;
                        actionType=WorkflowStep.ACTION_TYPE_END;
                    }            
                },*/
                //ConnectToDo    
            new ActionListener(){                                
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_LINE_TODO  ;
                        selectedColor = LINE_TODO_COLOR ;
                        selectedConnectName = AppletResource.lableArr[86];
                        selectedConnectType = WorkflowStep.PARENT_TYPE_SINGLE;
                        graph.setPortsVisible(ispending);                        
                    }            
                },
            //ConnectAutoTask    
            /*new ActionListener(){                                
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_LINE_TODO  ;
                        selectedConnectType = WorkflowStep.PARENT_TYPE_SINGLE;
                        selectedColor = LINE_TODO_COLOR ;
                        selectedConnectName = AppletResource.lableArr[86];
                        graph.setPortsVisible(true);                        
                    }            
                },
                //ConnectYes     
            new ActionListener(){                                
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_LINE_YES  ;
                        selectedColor = LINE_YES_COLOR ;
                        selectedConnectName = AppletResource.lableArr[90];
                        selectedConnectType = WorkflowStep.PARENT_TYPE_YES;
                        graph.setPortsVisible(true);                        
                    }            
                },
                //ConnectNot   
            new ActionListener(){                                
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_LINE_NOT  ;
                        selectedColor = LINE_NOT_COLOR ;
                        selectedConnectName = AppletResource.lableArr[89];
                        selectedConnectType = WorkflowStep.PARENT_TYPE_NO;
                        graph.setPortsVisible(true);                        
                    }            
                },
							//ConnectApprove   
            new ActionListener(){                                
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_LINE_APPROVE  ;
                        selectedColor = LINE_APPROVE_COLOR ;
                        selectedConnectName = AppletResource.lableArr[87];
                        selectedConnectType = WorkflowStep.PARENT_TYPE_APPROVED;
                        graph.setPortsVisible(true);                        
                    }            
                }, 
								//ConnectReject   
            new ActionListener(){                                
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_LINE_REJECT  ;
                        selectedColor = LINE_REJECT_COLOR ;
                        selectedConnectName = AppletResource.lableArr[88];
                        selectedConnectType = WorkflowStep.PARENT_TYPE_REJECTED;
                        graph.setPortsVisible(true);                        
                    }            
                }, 
                //ConnectCustom
            new ActionListener(){                                
                public void actionPerformed(ActionEvent e){
                        selectedType = SELECTED_TYPE_LINE_CUSTOM  ;
                        selectedColor = LINE_CUSTOM_COLOR;
                        selectedConnectName = CONNECTNAME_CUSTOM;
                        selectedConnectType = WorkflowStep.PARENT_TYPE_ROUTINE;
                        graph.setPortsVisible(true);                        
                    }            
                },
                //ConnectFormValueDriven
            new ActionListener(){                                
              public void actionPerformed(ActionEvent e){
                      selectedType = SELECTED_TYPE_FORM_VALUE_DRIVEN  ;
                      selectedColor = LINE_FORM_COLOR;
                      selectedConnectName = CONNECTNAME_FORM_VALUE_DRIVEN;
                      graph.setPortsVisible(true);                        
                  }            
              },
              //ConnectAutoTask
          new ActionListener(){                                
            public void actionPerformed(ActionEvent e){
                    selectedType = SELECTED_TYPE_AUTO_TASK  ;
                    selectedColor = LINE_AUTO_TASK_COLOR;
                    selectedConnectName = CONNECTNAME_AUTO_TASK;
                    selectedConnectType = WorkflowStep.PARENT_TYPE_SINGLE;
                    graph.setPortsVisible(true);                        
                }            
            },*/
            //undo
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  undo();
              }
            },
            //redo
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                redo();
              }
            },
            //copy
            new EventRedirector(TransferHandler.getCopyAction()),
            //paste
            new EventRedirector(TransferHandler.getPasteAction()),
            //cut
            new EventRedirector(TransferHandler.getCutAction()),
            //delete
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                if (!graph.isSelectionEmpty()) {
                  Object[] cells = graph.getSelectionCells();
                  cells = graph.getDescendants(cells);
                  graph.getModel().remove(cells);
                }
              }
            },
            //zoomout
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                graph.setScale(2 * graph.getScale());
              }
            },
            //zoomin
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                graph.setScale(0.5 * graph.getScale());
              }
            },
            //group
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                group(graph.getSelectionCells());
              }
            },
            //ungroup
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                ungroup(graph.getSelectionCells());
              }
            },
            //tofront
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                if (!graph.isSelectionEmpty())
                  toFront(graph.getSelectionCells());
              }
            },
            //toback
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                if (!graph.isSelectionEmpty())
                  toBack(graph.getSelectionCells());
              }
            },
            //layout
            new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                JDialog dialog = new LayoutDialog(graph);
                dialog.show();
              }
            },
        };
        jCBzoom.setEditable(true);
        jCBzoom.addItem("400%");
        jCBzoom.addItem("200%");
        jCBzoom.addItem("150%");
        jCBzoom.addItem("100%");
        jCBzoom.addItem("75%");
        jCBzoom.addItem("50%");
        jCBzoom.setSelectedIndex(3);
        jCBzoom.setMaximumSize(new Dimension(80,30));
        jCBzoom.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e){
            String zoomPercent = (String)jCBzoom.getSelectedItem();
            DecimalFormat nf = new DecimalFormat("#%");
            try{
              float zoom = nf.parse(zoomPercent).floatValue();
              graph.setScale(zoom);
            } catch(ParseException pe){
              
            }
            //System.out.println(workflowCategoryRecord);
          }
        });
        
        toggleButtons = new JButton [imageIcons.length ];
        for (int i = 0 ; i< imageIcons.length; i++ ){
                toggleButtons[i] = new JButton (imageIcons[i]);
                toggleButtons[i].setMargin(insets);
                toggleButtons[i].addActionListener( actionListeners[i]);                
        }                                                                      
                
        for(int i = 0 ; i< toggleButtons.length ;i++ ){
            toggleButtons[i].setToolTipText(toolbarTitle[i]);
            toolTipMenuGroup.add(toggleButtons[i]);
            if(i==2||i==10){
              toolbar.addSeparator(); 
            }
            if(i==16){
              toolbar.add(jCBzoom);
            }
            toolbar.add(toggleButtons[i]);    
        }
        
        toggleButtons[0].setSelected(true);
        
        return toolbar;
    }

    // This will change the source of the actionevent to graph.
    protected class EventRedirector extends AbstractAction {

        protected Action action;

        // Construct the "Wrapper" Action
        public EventRedirector(Action a) {
            super("", (ImageIcon) a.getValue(Action.SMALL_ICON));
            this.action = a;
        }

        // Redirect the Actionevent
        public void actionPerformed(ActionEvent e) {
            e =
                new ActionEvent(
                    graph,
                    e.getID(),
                    e.getActionCommand(),
                    e.getModifiers());
            action.actionPerformed(e);
        }
    }
    
    // insertStartStep 
    public void insertStartStep() {
        Point2D point = new Point(10, 150) ;
        //get start step from workflowStepList         
        //WorkflowStepRecord workflowStepRecord = getWorkflowStepRecordBySeq(1);
        //workflowStepRecord.setStepSeq(new Integer("1"));
        //workflowStepRecord.setStepIndex(0);        
        //workflowStepRecord.setStepType(STEP_START);
        // Construct Vertex with binding  steprecord
        DefaultGraphCell vertex = new DefaultGraphCell("1.Start WorkFlow");
        // Add one Floating Port
        vertex.add(new DefaultPort());
        // Snap the Point to the Grid
        point = graph.snap(point);
        // Default Size for the new Vertex
        Dimension2D size = new Dimension(100,30);
        // Create a Map that holds the attributes for the Vertex
        Map map = new Hashtable();
        // Add a Bounds Attribute to the Map
        GraphConstants.setBounds(map, new Rectangle2D.Double(point.getX(),point.getY(), size.getWidth(), size.getHeight()));
        // Add a Border Color Attribute to the Map
        GraphConstants.setBorderColor(map, Color.black);
        // Add a White Background
        GraphConstants.setBackground(map, START_COLOR);
        //Edit disable 
        GraphConstants.setEditable(map, false);
        // Make Vertex Opaque
        GraphConstants.setOpaque(map, true);
        //GraphConstants.setFont( map,Color.BLUE);
        GraphConstants.setForeground( map,Color.WHITE );        
        // Set Icon    
        //GraphConstants.setIcon(map,iIcon);
        // Construct a Map from cells to Maps (for insert)
        Hashtable attributes = new Hashtable();
        // Associate the Vertex with its Attributes
        attributes.put(vertex, map);
        //vertex.setUserObject("test");
        // Insert the Vertex and its Attributes (can also use model)
        graph.getGraphLayoutCache().insert(
            new Object[] { vertex },
            attributes,
            null,
            null,
            null);
        //vertex.setUserObject("changed");
        //CellView view = graph.getMapping(vertex, false);
        //view.update();
    }
    

    // insertEndStep     
    public void insertEndStep() {
        Point2D point = new Point(10, 300);    
//        WorkflowStepRecord workflowStepRecord = new WorkflowStepRecord();
//        workflowStepRecord.setStepName("End");
        //get start step from workflowStepList
        WorkflowStepRecord workflowStepRecord = getWorkflowStepRecordByID(999999999);
        workflowStepRecord.setStepType(STEP_END);  
        workflowStepRecord.setStepIndex(999999999);
        DefaultGraphCell vertex = new DefaultGraphCell();        // Add one Floating Port
        GPUserObject userObject =new GPUserObject();
        userObject.putProperty("1","show");
        userObject.setValue("start");
        vertex.setUserObject(userObject);
        vertex.add(new DefaultPort());
        // Snap the Point to the Grid
        point = graph.snap(point);
        // Default Size for the new Vertex
        Dimension size = new Dimension(100,30);
        // Create a Map that holds the attributes for the Vertex
        Map map = new Hashtable();
        //Map map = createCellAttributes(point);
        // Add a Bounds Attribute to the Map
        GraphConstants.setBounds(map, new Rectangle2D.Double(point.getX(),point.getY(), size.getWidth(), size.getHeight()));
        // Add a Border Color Attribute to the Map
        GraphConstants.setBorderColor(map, Color.black);
        // Add a White Background
        GraphConstants.setBackground(map, END_COLOR);
        //      Edit disable 
        GraphConstants.setEditable(map, false);
        // Make Vertex Opaque
        GraphConstants.setOpaque(map, true);
        //GraphConstants.setFontStyle( map,1);
        GraphConstants.setForeground( map,Color.WHITE );
        
        // Set Icon    
        //GraphConstants.setIcon(map,iIcon);
        // Construct a Map from cells to Maps (for insert)
        Hashtable attributes = new Hashtable();
        // Associate the Vertex with its Attributes
        attributes.put(vertex, map);
        // Insert the Vertex and its Attributes (can also use model)
        graph.getGraphLayoutCache().insert(
            new Object[] { vertex },
            attributes,
            null,
            null,
            null);
    }    
    
    //initEditor
    public void initEditor(){
        //get this workflow record containt step information
      buildTreeByDB(); 
      String[] xmlArray = expToArray(graph);
      graph.getModel().remove(graph.getAll());
      boolean existInServer =getChartByXml();
      Object[] cells=null;
      if(existInServer){
        cells = graph.getRoots();
      } else {
        buildTreeByDB(); 
        return;
      }
      String[] dbArray = expToArray(graph);
      
      graph.getModel().remove(graph.getAll());
      if(Arrays.equals(xmlArray,dbArray)){                
        getChartByXml();
      } else {
        buildTreeByDB();
      }
      //insertEndStep();
      
      
      
      //if(!getChartFromServer()){
        //insertStartStep();
        //insertEndStep();
      //}
        //setEnabled(true);
    }
    
    //saveEditor
    public void saveEditor(){
/*        
        try {        
            FileOutputStream fos = new FileOutputStream(new File("D://Test.gxl"));
            // Created writer with UTF-8 encoding
            Writer out = new OutputStreamWriter(fos, "UTF-8");
            // Write the SVG file
            write(graph, out);
        } catch (Exception e) {
            // Display error message on stderr
            System.err.println(e.toString());
        }
*/                
    }
    
    //closeEditor
    public void closeEditor (){
        setEnabled(false);        
        Object[] cells = graph.getDescendants(graph.getRoots());
        graph.getModel().remove(cells);
        //graph.setVisible(false);
    }
    
    public void setEnabled(boolean enabled){
        this.enable  =  enabled;           
        for(int i = 0 ; i < toggleButtons.length ; i++ ){
            toggleButtons[i].setEnabled(enabled);
        }       
    }

    public boolean getEnabled(){
        return this.enable;     
    }
    
    public void setWorkflowRecordID(Integer workflowRecordID){
        this.workflowRecordID = workflowRecordID;    
    }
    
    public void setIspending(boolean ispending){
      this.ispending = ispending;    
  }
    
    public Integer getWorkflowRecordID(){
        return this.workflowRecordID;    
    } 
    
    public void setWorkflowStepList(List workflowStepList){
        this.workflowStepList = workflowStepList;    
    }    
    
    public List getWorkflowStepList(){
        return this.workflowStepList;    
    }
        
    public WorkflowStepRecord getWorkflowStepRecordBySeq(int stepSeq){
        WorkflowStepRecord workflowStepRecord = new WorkflowStepRecord();
        for (int i = 0 ;i < workflowStepList.size() ;i++){
            WorkflowStep tempRecord = (WorkflowStep)workflowStepList.get(i);
            if (tempRecord.getStepSeq().intValue()  == stepSeq){
                workflowStepRecord.setID(tempRecord.getID());
                workflowStepRecord.setWorkflowRecordID(tempRecord.getWorkflowRecordID());
                workflowStepRecord.setStepSeq(tempRecord.getStepSeq());
                workflowStepRecord.setStepName(tempRecord.getStepName());
                workflowStepRecord.setActionType(tempRecord.getActionType());
                workflowStepRecord.setActionID(tempRecord.getActionID());
                workflowStepRecord.setDescription(tempRecord.getDescription());
                workflowStepRecord.setWorkflowRule(tempRecord.getWorkflowRule());
                workflowStepRecord.setCategoryID(tempRecord.getCategroyID()) ;
                workflowStepRecord.setPriority(tempRecord.getPriority());
                workflowStepRecord.setAllowAssignDueDate(tempRecord.getAllowAssignDueDate());
                workflowStepRecord.setNextStepAllowAssignDueDate(tempRecord.getNextStepAllowAssignDueDate());
                workflowStepRecord.setOnCompleteAckMethod(tempRecord.getOnCompleteAckMethod());
                workflowStepRecord.setOnNoResponseFor(tempRecord.getOnNoResponseFor());
                workflowStepRecord.setOnNoResponseAfter(tempRecord.getOnNoResponseAfter());
                workflowStepRecord.setOnNoResponseAction(tempRecord.getOnNoResponseAction());
                workflowStepRecord.setOnNoResponseNextStepID(tempRecord.getOnNoResponseNextStepID());
                workflowStepRecord.setOnNoResponseAckMethod(tempRecord.getOnNoResponseAckMethod());
                workflowStepRecord.setFilterBy(tempRecord.getFilterBy());
                workflowStepRecord.setNotifyOwnerTaskArrivalByMail(tempRecord.getNotifyOwnerTaskArrivalByMail());
                workflowStepRecord.setNotifyAllTaskCompletedByMail(tempRecord.getNotifyAllTaskCompletedByMail());
                workflowStepRecord.setNotifyOwnerTaskOverdueByMail(tempRecord.getNotifyOwnerTaskOverdueByMail());
                workflowStepRecord.setNotifyAllTaskOverdueBySystem(tempRecord.getNotifyAllTaskOverdueBySystem());
                workflowStepRecord.setNotifyAllTaskOverdueByMail(tempRecord.getNotifyAllTaskOverdueByMail());
                workflowStepRecord.setNotifyOwnerTaskArrivalBySystem(tempRecord.getNotifyOwnerTaskArrivalBySystem());
                workflowStepRecord.setNotifyAllTaskCompletedBySystem(tempRecord.getNotifyAllTaskCompletedBySystem());
                workflowStepRecord.setNotifyOwnerTaskOverdueBySystem(tempRecord.getNotifyOwnerTaskOverdueBySystem());            
                workflowStepRecord.setParentStepIDs(tempRecord.getParentStepIDs());
                workflowStepRecord.setUserRecords(tempRecord.getUserRecords());
                workflowStepRecord.setUserGroups(tempRecord.getUserGroups());
                workflowStepRecord.setUserRoles(tempRecord.getUserRoles());
                workflowStepRecord.setActorType(tempRecord.getActorType());
                workflowStepRecord.setParentStepID(tempRecord.getParentStepID());
                workflowStepRecord.setLoopBackStepID(tempRecord.getLoopBackStepID());
                workflowStepRecord.setParentType(tempRecord.getParentType());
                workflowStepRecord.setCurrentStepID(tempRecord.getCurrentStepID());
                workflowStepRecord.setOverDueType(tempRecord.getOverDueType());
                workflowStepRecord.setRouteListValue(tempRecord.getRouteListValue());
                workflowStepRecord.setFormRecordID(tempRecord.getFormRecordID());
                workflowStepRecord.setOperand1(tempRecord.getOperand1());
                workflowStepRecord.setOperand2(tempRecord.getOperand2());
                workflowStepRecord.setCompare(tempRecord.getCompare());
                workflowStepRecord.setFormEquation(tempRecord.getFormEquation());
                workflowStepRecord.setOperationTypeForFormEquat(tempRecord.getOperationTypeForFormEquat());
                workflowStepRecord.setDateFormat(tempRecord.getDateFormat());
            
                workflowStepRecord.setRecordStatus(tempRecord.getRecordStatus());
                workflowStepRecord.setUpdateCount(tempRecord.getUpdateCount());
                workflowStepRecord.setCreatorID(tempRecord.getCreatorID());
                workflowStepRecord.setCreateDate(tempRecord.getCreateDate());
                workflowStepRecord.setUpdaterID((tempRecord.getUpdaterID()));
                workflowStepRecord.setUpdateDate(tempRecord.getUpdateDate());           
                
                workflowStepRecord.setSectionID("0|0");                
                
            }    
        }            
        return  workflowStepRecord;
    }
    
    public WorkflowStepRecord getWorkflowStepRecordByID(int stepSeq){
      WorkflowStepRecord workflowStepRecord = new WorkflowStepRecord();
      return  workflowStepRecord;
    }
    
    
    void saveChartToServer(){        
      try
        {
        //clearMessage();
        List parentStepSeqList = new ArrayList();
        List childStepSeqList = new ArrayList();
        List parentStepTypeList = new ArrayList();
        List parentStepActionTypeList = new ArrayList();
        List stepSeqList = new ArrayList();
        List connectionList = new ArrayList();
        List stepList = new ArrayList();
        List formValueDrivenList = new ArrayList();
        Object[] cells = graph.getRoots();        
        String[][] stepRelationArray = new String[cells.length][3];
        String[] stepArray = new String[cells.length];
        DefaultEdge edge;
        boolean stepIsOK = true;
        // get the cell relationship and cell type
        for(int i = 0 ;i<cells.length ;i++){
          if(cells[i] != null){                
              //get edge
              if (cells[i] instanceof DefaultEdge ) {
                  edge = (DefaultEdge)cells[i];
                  connectionList.add(edge);
              }
              //get cell
              else if (cells[i] instanceof DefaultGraphCell) {
                  DefaultGraphCell getCell = (DefaultGraphCell)cells[i];
                  stepList.add(getCell);
              }
          }
        }
        if(!checkChart(connectionList, stepList)){
          return;
        }
        //change the format of type form "type_name" to "seq_type_name"
        assignSeqID(stepList);
        for(int i = 0 ;i<cells.length ;i++){
            if(cells[i] != null){                
                //get edge
                if (cells[i] instanceof DefaultEdge ) {
                    edge = (DefaultEdge)cells[i];
                    GPUserObject connectType = (GPUserObject)edge.getUserObject();
                    String connectionType = connectType.getProperty("TYPE").toString();
                    if(connectionType.equals(WorkflowStep.PARENT_TYPE_YES)){
                        parentStepTypeList.add(WorkflowStep.PARENT_TYPE_YES);
                        parentStepActionTypeList.add("B");
                    }else if(connectionType.equals(WorkflowStep.PARENT_TYPE_NO)){
                      parentStepTypeList.add(WorkflowStep.PARENT_TYPE_NO);
                      parentStepActionTypeList.add("B");
                  }else if(connectionType.equals(WorkflowStep.PARENT_TYPE_REJECTED)){
                      parentStepTypeList.add(WorkflowStep.PARENT_TYPE_REJECTED);
                      parentStepActionTypeList.add("A");
                    }else if(connectionType.equals(WorkflowStep.PARENT_TYPE_APPROVED)){
                      parentStepTypeList.add(WorkflowStep.PARENT_TYPE_APPROVED);
                      parentStepActionTypeList.add("A");
                    }else if(connectionType.equals(WorkflowStep.PARENT_TYPE_SINGLE)){
                      parentStepTypeList.add("S");
                      parentStepActionTypeList.add("T");
                    }else if(connectionType.indexOf("U"+AppletConstant.SPLITCHAR)>0){
                      parentStepTypeList.add(connectionType);
                      parentStepActionTypeList.add(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK);
                    }else if(connectionType.indexOf("D"+AppletConstant.SPLITCHAR)>0){
                      parentStepTypeList.add(connectionType);
                      parentStepActionTypeList.add(WorkflowStep.ACTION_TYPE_FORM_DRIVEN);
                      GPUserObject userObject = (GPUserObject)edge.getUserObject();
                      formValueDrivenList.add(userObject.getProperty("EQUATION")) ;                    
                    }else{
                      parentStepTypeList.add(connectionType);
                      parentStepActionTypeList.add("T");
                    }
                    String showName = ((DefaultGraphCell)((DefaultPort)edge.getSource()).getParent()).getUserObject().toString();
                    parentStepSeqList.add((WindowUtilities.splitString(showName,"."))[0]);
                    showName = ((DefaultGraphCell)((DefaultPort)edge.getTarget()).getParent()).getUserObject().toString();
                    childStepSeqList.add((WindowUtilities.splitString(showName,"."))[0]);

                }
                //get cell
                else if (cells[i] instanceof DefaultGraphCell) {
                    DefaultGraphCell getCell = (DefaultGraphCell)cells[i];
                    String showName = getCell.getUserObject().toString();
                    if(showName != null){          
                        stepArray[i] = showName;
                        stepSeqList.add(showName);
                    }                    
                }       
            }    
        }
        
        //test
        //MoenLayoutAlgorithm circleGraphLayout = new MoenLayoutAlgorithm();
        //circleGraphLayout.run(graph, cells);
        //if(true)return ;
        //for
        DefaultGraphModelFileFormatXML defaultgraphmodelfileformatxml = DefaultGraphModelFileFormatXML.instance();
        
        String maintWorkflowRecordURL = "/workflow/MaintWorkflowConnection.do";        
        httpOperation.reset() ;
        httpOperation.setSubmissionURL(maintWorkflowRecordURL);

        for(int i=0;i<parentStepSeqList.size();i++)
        {          
          httpOperation.addHtmlFormText(new HtmlFormText("parentStepSeq", (String)parentStepSeqList.get(i)));
          httpOperation.addHtmlFormText(new HtmlFormText("childStepSeq", (String)childStepSeqList.get(i)));
          httpOperation.addHtmlFormText(new HtmlFormText("parentStepType", (String)parentStepTypeList.get(i)));
          httpOperation.addHtmlFormText(new HtmlFormText("parentStepActionType", (String)parentStepActionTypeList.get(i)));
          httpOperation.addHtmlFormText(new HtmlFormText("loopBack", "N"));
        }
        for(int i=0;i<stepSeqList.size();i++){
          String showName = (String)stepSeqList.get(i);
          if(showName.indexOf('.')>0){
            httpOperation.addHtmlFormText(new HtmlFormText("stepSeq", (WindowUtilities.splitString(showName,"."))[0]));  
          }          
        }
        httpOperation.addHtmlFormText(new HtmlFormText("navMode", "N"));
        httpOperation.addHtmlFormText(new HtmlFormText("opMode", "INS"));
        httpOperation.addHtmlFormText(new HtmlFormText("workflowRecordID", workflowRecordID.toString()));
        httpOperation.addHtmlFormText(new HtmlFormText("workflowChart", defaultgraphmodelfileformatxml.toString(graph)));
                       
        String returnValue = httpOperation.transmit().toString();
        returnValue = returnValue.replaceAll("\n","");
       
        outputMessage(returnValue, false);
        //FileExportJPG fileExportJPG = new FileExportJPG(graph);
        //java.awt.image.BufferedImage bufferedimage = JGraphUtilities.toImage(graph, 5);
        //ImageIO.write(bufferedimage, "jpg", new File("c:/new.jpg"));

        
        //defaultgraphmodelfileformatxml.write(new URL("file:///c:/url.xml"), graph, graph.getModel());
        //gpdocument.setFilename("c:/Test.xml");
        //gpdocument.setModified(false);
          }
          catch(Exception e)
          {
            //JOptionPane.showMessageDialog(graph, exception.getLocalizedMessage(), Translator.getString("Error"), 0);
            e.printStackTrace(System.out);
          }
          finally
          {
              //graph.update();
              graph.invalidate();
          }
    }
    
    void assignSeqID(List stepList){
      for(int i=0; i<stepList.size(); i++){
        DefaultGraphCell stepCell = (DefaultGraphCell)stepList.get(i);
        DefaultPort stepPort = (DefaultPort)stepCell.getFirstChild();
        Iterator connectionIterator = stepPort.edges();
        Iterator connectionIteratorClone = stepPort.edges();
        List childStepconnectionList = new ArrayList();
        List parentStepconnectionList = new ArrayList();
        
        while(connectionIterator.hasNext()){
          DefaultEdge connection = (DefaultEdge)connectionIterator.next();
          if(((DefaultPort)connection.getSource())==stepPort){
            childStepconnectionList.add(connection);            
          }else if(((DefaultPort)connection.getTarget())==stepPort){
            parentStepconnectionList.add(connection);
          }
        }
        int k=0;
        GPUserObject stepType = (GPUserObject)stepCell.getUserObject();
        String actionType = (String)stepType.getProperty("STEPTYPE");
        if(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(actionType)||WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(actionType)){
          for(int j=0;j<childStepconnectionList.size();j++){
            GPUserObject routeType = (GPUserObject)((DefaultEdge)childStepconnectionList.get(j)).getUserObject();
            String parentType = routeType.getProperty("TYPE").toString();
            String[] routeInfo = WindowUtilities.splitString(parentType,AppletConstant.SPLITCHAR);
            if(routeInfo.length>2){
              parentType=k+AppletConstant.SPLITCHAR+routeInfo[1]+AppletConstant.SPLITCHAR+routeInfo[2];
            }else{
              parentType=k+AppletConstant.SPLITCHAR+parentType;
            }            
            k++;
            routeType.putProperty("TYPE",parentType);
          }
        }
        
      }
    }
    
    boolean checkChart(List connectionList, List stepList){
      for(int i=0; i<stepList.size(); i++){
        DefaultGraphCell stepCell = (DefaultGraphCell)stepList.get(i);
        DefaultPort stepPort = (DefaultPort)stepCell.getFirstChild();
        Iterator connectionIterator = stepPort.edges();
        Iterator connectionIteratorClone = stepPort.edges();
        List childStepconnectionList = new ArrayList();
        List parentStepconnectionList = new ArrayList();
        while(connectionIterator.hasNext()){
          DefaultEdge connection = (DefaultEdge)connectionIterator.next();
          if(((DefaultPort)connection.getSource())==stepPort){
            childStepconnectionList.add(connection);            
          }else if(((DefaultPort)connection.getTarget())==stepPort){
            parentStepconnectionList.add(connection);
          }
        }
        
        if(stepCell.toString().indexOf(".")<0){
          if(connectionIteratorClone.hasNext()){
            AppletResource.lableArr[299]=stepCell.toString();
            String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{1,299});
            outputMessage(message, false);
            return false;
          }          
        }
        String stepSeq = WindowUtilities.splitString(stepCell.toString(), ".")[0];
        if("1".equals(stepSeq)){
          for(int j=0;j<childStepconnectionList.size();j++){
            String type = ((GPUserObject)((DefaultEdge)childStepconnectionList.get(j)).getUserObject()).getProperty("TYPE").toString();
            if(!WorkflowStep.PARENT_TYPE_SINGLE.equals(type)){
              AppletResource.lableArr[299]=stepCell.toString();
              String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{2,299});
              outputMessage(message, false);
              return false;
            }            
          }
          continue;
        } else if("999999999".equals(stepSeq)){
          if(childStepconnectionList.size()!=0){
            AppletResource.lableArr[299]=stepCell.toString();
            String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{3,299});
            outputMessage(message, false);
            return false;
          } else {
            continue;
          }
        }
        /*if(parentStepconnectionList.size()==0){
          outputMessage(stepCell+" should have parent step, since it is not a start step!", false);
          return false;
        } */
        if(childStepconnectionList.size()==0){
          continue;
        }               
        String type = ((GPUserObject)((DefaultEdge)childStepconnectionList.get(0)).getUserObject()).getProperty("TYPE").toString();
        if(WorkflowStep.PARENT_TYPE_SINGLE.equals(type)){
          for(int j=0;j<childStepconnectionList.size();j++){
            String otherType = ((GPUserObject)((DefaultEdge)childStepconnectionList.get(j)).getUserObject()).getProperty("TYPE").toString();
            if(!WorkflowStep.PARENT_TYPE_SINGLE.equals(otherType)){
              AppletResource.lableArr[299]=stepCell.toString();
              String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{4,299});
              outputMessage(message, false);
              return false;
            }
          }
        } else if(WorkflowStep.PARENT_TYPE_YES.equals(type)||WorkflowStep.PARENT_TYPE_NO.equals(type)){
          for(int j=0;j<childStepconnectionList.size();j++){
            String otherType = ((GPUserObject)((DefaultEdge)childStepconnectionList.get(j)).getUserObject()).getProperty("TYPE").toString();
            if(!WorkflowStep.PARENT_TYPE_YES.equals(otherType)&&!WorkflowStep.PARENT_TYPE_NO.equals(otherType)){
              AppletResource.lableArr[299]=stepCell.toString();
              String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{5,299});
              outputMessage(message, false);
              return false;
            }
          }            
        } else if(WorkflowStep.PARENT_TYPE_APPROVED.equals(type)||WorkflowStep.PARENT_TYPE_REJECTED.equals(type)){
          for(int j=0;j<childStepconnectionList.size();j++){
            String otherType = ((GPUserObject)((DefaultEdge)childStepconnectionList.get(j)).getUserObject()).getProperty("TYPE").toString();
            if(!WorkflowStep.PARENT_TYPE_APPROVED.equals(otherType)&&!WorkflowStep.PARENT_TYPE_REJECTED.equals(otherType)){
              AppletResource.lableArr[299]=stepCell.toString();
              String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{6,299});
              outputMessage(message, false);
              return false;
            }
          }     
        } else if(type.length()>1&&CONNECTNAME_CUSTOM.equals(type.substring(0,2))){
          for(int j=0;j<childStepconnectionList.size();j++){
            String otherType = ((GPUserObject)((DefaultEdge)childStepconnectionList.get(j)).getUserObject()).getProperty("TYPE").toString();
            if(otherType.length()<=1||!CONNECTNAME_CUSTOM.equals(otherType.substring(0,2))){
              AppletResource.lableArr[299]=stepCell.toString();
              String message = WindowUtilities.getResouceByCode(httpOperation, hostURL, new int[]{7,299});
              outputMessage(message, false);
              return false;
            }
          }
        }

        /*
        Object firstConnection = childStepconnectionList.get(0);
        if(CONNECTNAME_TODO.equals(firstConnection.toString())){
          if(childStepconnectionList.size()>1){
            messageTextArea.append(stepCell+" should not have more than one ToDo route!"+"\n");
            return false;
          }
        } else if(CONNECTNAME_YES.equals(firstConnection.toString())||CONNECTNAME_NOT.equals(firstConnection.toString())){
          if(childStepconnectionList.size()>2){
            messageTextArea.append(stepCell+" should not have more than two child steps!"+"\n");
            return false;
          } else {
            for(int j=1;j<childStepconnectionList.size();j++){
              if(!CONNECTNAME_YES.equals(childStepconnectionList.get(j).toString())&&!CONNECTNAME_NOT.equals(childStepconnectionList.get(j).toString())){
                messageTextArea.append(stepCell+" should not have more than one type of child step!"+"\n");
                return false;
              }
            }
          }
          
        } else if(CONNECTNAME_APPROVE.equals(firstConnection.toString())||CONNECTNAME_REJECT.equals(firstConnection.toString())){
          if(childStepconnectionList.size()>2){
            messageTextArea.append(stepCell+" should not have more than two child steps!"+"\n");
          } else {
            for(int j=1;j<childStepconnectionList.size();j++){
              if(!CONNECTNAME_APPROVE.equals(childStepconnectionList.get(j).toString())&&!CONNECTNAME_REJECT.equals(childStepconnectionList.get(j).toString())){
                messageTextArea.append(stepCell+" should not have more than one type of child step!"+"\n");
                return false;
              }
            }
          }
          
        } else if(CONNECTNAME_CUSTOM.equals(firstConnection.toString())){
          for(int j=1;j<childStepconnectionList.size();j++){
            if(!CONNECTNAME_CUSTOM.equals(firstConnection.toString())){
              messageTextArea.append(stepCell+" should not have more than one type of child step!"+"\n");
              return false;
            }
          }
        }*/ 
      }
      return true;
    }
    
    boolean getChartByXml(){
        ObjectInputStream inputFromServlet = null;
        String getDataURL  = "/workflow/appletMiddleware?dataType=GET_WORKFLOWCHART&workflowRecordID="+workflowRecordID;
      try{
        inputFromServlet = httpOperation.getObjectInputStreamFromServlet(getDataURL);

        if(inputFromServlet == null){
          return false;
        }

        Object obj = null;
        String workflowChart = null;
        //obj = inputFromServlet.readObject();
      //  get bind list for select
        obj = inputFromServlet.readObject();
        if (obj instanceof String) {
          workflowChart = (String) obj;
        } else if (obj instanceof Exception) {
          //otherwise type cast it to Exception and throw that exception.
        throw (Exception) obj;
        }
        if(Utility.isEmpty(workflowChart)){
          return false;   
        }
        ByteArrayInputStream BAIS = new ByteArrayInputStream(workflowChart.getBytes());        
        DefaultGraphModelFileFormatXML.read(BAIS,graph);
        AttributeMap map = new AttributeMap();
        GraphConstants.setRouting(map, FormatRoutingParallel.parallelEdgeRouter);
        GraphConstants.setRemoveAttributes(
          map,
          new Object[] { GraphConstants.POINTS });
        //graphpad.getCurrentDocument().setSelectionAttributes(map);
        map.remove(GraphConstants.BOUNDS);
        map.remove(GraphConstants.POINTS);
        JGraphUtilities.editCells(graph, graph.getRoots(), map);

      }catch(Exception e){
          e.printStackTrace();
          return false;
      }
      return true;
         
    }
    public boolean buildTreeByDB(){
      ObjectInputStream inputFromServlet = null;
      String getDataURL  = "/workflow/appletMiddleware?dataType=BUILD_TREE&workflowRecordID="+workflowRecordID;
      Integer [][] IDSeq;
      try{
        inputFromServlet = httpOperation.getObjectInputStreamFromServlet(getDataURL);
        if(inputFromServlet == null){
          return false;
        }
  
        Object obj = null;
        List workflowSteps = null;
        //obj = inputFromServlet.readObject();
      //  get bind list for select
        obj = inputFromServlet.readObject();
        if (obj instanceof List) {
          workflowSteps = (List) obj;
        } else if (obj instanceof Exception) {
          //otherwise type cast it to Exception and throw that exception.
        throw (Exception) obj;
        }
        if(Utility.isEmpty(workflowSteps)){
          return false;   
        }
        IDSeq = new Integer[workflowSteps.size()][2];
        DefaultPort[] cellPort = new DefaultPort[workflowSteps.size()];
        for(int i=0;i<workflowSteps.size();i++){
          WorkflowStep workflowStep = (WorkflowStep)workflowSteps.get(i);
          IDSeq[i][0] = workflowStep.getID();
          IDSeq[i][1] = workflowStep.getStepSeq();
          String showValue = workflowStep.getStepSeq().toString()+"."+workflowStep.getStepName();
          Point2D point = new Point(100, 50*i) ;
          cellPort[i] = insertNewStep(point,workflowStep);        
        }
        List stepConnections = null;
        //obj = inputFromServlet.readObject();
      //  get bind list for select
        obj = inputFromServlet.readObject();
        if (obj instanceof List) {
          stepConnections = (List) obj;
        } else if (obj instanceof Exception) {
          //otherwise type cast it to Exception and throw that exception.
        throw (Exception) obj;
        }
        for(int i=0;i<stepConnections.size();i++){
          MtmWorkflowStepWorkflowStep stepConnection = (MtmWorkflowStepWorkflowStep)stepConnections.get(i);
          Integer parentStepID = stepConnection.getParentStepID();
          Integer childStepID = stepConnection.getChildStepID();
          String parentType = stepConnection.getParentType();
          DefaultPort parentStepPort=null, childStepPort=null;
          for(int j=0;j<IDSeq.length;j++){
            if(IDSeq[j][0].equals(parentStepID)){
              parentStepPort = cellPort[j];
            }
            if(IDSeq[j][0].equals(childStepID)){
              childStepPort = cellPort[j];
            }
          }
          if(parentStepPort==null||childStepPort==null){
            continue;
          } else {
            connectSteps(parentStepPort, childStepPort, parentType, parentStepID);
          }
        }
        SugiyamaLayoutAlgorithm layout = new SugiyamaLayoutAlgorithm();
        layout.setSpacing(new Point(150,100));
        JGraphLayoutAlgorithm.applyLayout(graph,layout, graph.getRoots(),null );
      }catch(IllegalArgumentException e){
        CircleGraphLayout layout = new CircleGraphLayout();
        JGraphLayoutAlgorithm.applyLayout(graph,layout, graph.getRoots(),null );
      }
      catch(Exception e){
          e.printStackTrace();
          return false;
      }
      return true;
         
    }
    
    boolean connectSteps(DefaultPort parentStepPort, DefaultPort childStepPort, String parentType, Integer parentStepID){
      DefaultGraphCell parentStep  = (DefaultGraphCell)parentStepPort.getParent();
      String parentStepActionType = (String)((GPUserObject)parentStep.getUserObject()).getProperty("STEPTYPE");
      if(CONNECTNAME_TODO_DB.equals(parentType)){
        selectedType = SELECTED_TYPE_LINE_TODO  ;
        selectedColor = LINE_TODO_COLOR ;
        selectedConnectName = AppletResource.lableArr[86];
      } else if(CONNECTNAME_YES_DB.equals(parentType)) {
        selectedType = SELECTED_TYPE_LINE_YES  ;
        selectedColor = LINE_YES_COLOR ;
        selectedConnectName = AppletResource.lableArr[90];
      } else if(CONNECTNAME_NOT_DB.equals(parentType)) {
        selectedType = SELECTED_TYPE_LINE_NOT  ;
        selectedColor = LINE_NOT_COLOR ;
        selectedConnectName = AppletResource.lableArr[89];
      } else if(CONNECTNAME_APPROVE_DB.equals(parentType)) {
        selectedType = SELECTED_TYPE_LINE_APPROVE  ;
        selectedColor = LINE_APPROVE_COLOR ;
        selectedConnectName = AppletResource.lableArr[87];
      } else if(CONNECTNAME_REJECT_DB.equals(parentType)) {
        selectedType = SELECTED_TYPE_LINE_REJECT  ;
        selectedColor = LINE_REJECT_COLOR ;
        selectedConnectName = AppletResource.lableArr[88];
      } else if(parentType.length()>1&&parentType.substring(0,1).equals(CONNECTNAME_CUSTOM_DB)) {
        ObjectInputStream inputFromServlet = null;
        String routeSeq = parentType.substring(1);
        String getDataURL  = "/workflow/appletMiddleware?dataType=STEP_ROUTE&stepID="+parentStepID.toString()+"&routeSeq="+routeSeq+"&actionType="+parentStepActionType;
        Integer [][] IDSeq;
        try{
          inputFromServlet = httpOperation.getObjectInputStreamFromServlet(getDataURL);
          if(inputFromServlet == null){
            return false;
          }    
          Object obj = null;
          String routeName = "";
          //obj = inputFromServlet.readObject();
        //  get bind list for select
          obj = inputFromServlet.readObject();
          if (obj instanceof String) {
            routeName = (String) obj;//routeName is something like parenttype#routelabel
          } else if (obj instanceof Exception) {
            //otherwise type cast it to Exception and throw that exception.
            throw (Exception) obj;
          }
          selectedConnectName = WindowUtilities.splitString(routeName,"&")[1];
          parentType=WindowUtilities.splitString(routeName,"&")[0];;
          
        }catch(Exception e){
          e.printStackTrace();
          return false;
        }
        
        selectedType = SELECTED_TYPE_LINE_CUSTOM  ;
        selectedColor = LINE_CUSTOM_COLOR ;
        //selectedConnectName = CONNECTNAME_CUSTOM+parentType.substring(1);
      }
      initConnect(parentStepPort, childStepPort, parentType);
      return true;
    }
  /**
  * save Editor To System
  *
  */
    public void save() throws Exception{
        
    
    }    
    
  /**
  * getStepIndexByEdge
  * 
  *  @param      edge       edge
  *  @param      getType    get which step's stepIndex,"SOURCE" : getSource;"TARGET" :getTarget
  * 
  *  @return     int        Return the action forward object for struts
  */    
    public int getStepIndexByEdge(DefaultEdge edge,String getType){
      int returnValue = -1;  
      if(edge == null){  
        returnValue = -1;
      }      
      if ("SOURCE".equals(getType)){
        returnValue = ((WorkflowStepRecord)((DefaultGraphCell)((DefaultPort)edge.getSource()).getParent()).getUserObject()).getStepIndex();;        
      }else if ("TARGET".equals(getType)){
        returnValue = ((WorkflowStepRecord)((DefaultGraphCell)((DefaultPort)edge.getTarget()).getParent()).getUserObject()).getStepIndex();;        
      }      
      return returnValue;
    }
    
  /**
  * getCellByStepIndex
  * @param      stepIndex 
  *
  * @return  return the cell of allthe graph's contant by stepIndex
  */    
    public DefaultGraphCell getCellByStepIndex(int stepIndex){
        DefaultGraphCell returnCell = null;
        Object[] cells = graph.getRoots();        
        for(int i = 0 ;i<cells.length ;i++){
            DefaultGraphCell getCell = (DefaultGraphCell)cells[i];
            WorkflowStepRecord workflowStepRecord = (WorkflowStepRecord)getCell.getUserObject();
            if(workflowStepRecord != null){                
                if (stepIndex == workflowStepRecord.getStepIndex()){                    
                    returnCell = getCell;
                    break;
                }
            }
        }        
        return returnCell;        
    }

    public String[] expToArray(GPGraph graph){
      Object[] cells = graph.getRoots();
      int length = cells.length;
      DefaultEdge[] connections = new DefaultEdge[length];
      String[] connectionsStr = new String[length];
      for(int i=0;i<cells.length;i++){
        if(cells[i] != null){                
          //get edge
          if (cells[i] instanceof DefaultEdge ) {
            connections[i] = (DefaultEdge)cells[i];
            String connectionType = ((GPUserObject)connections[i].getUserObject()).getProperty("TYPE").toString();
            connectionsStr[i] = ((DefaultPort)connections[i].getTarget()).getParent().toString()
            +"#"+connections[i].toString()
            +"#"+connectionType
            +"#"+((DefaultPort)connections[i].getSource()).getParent().toString();
          }
        }
      }
      for(int i=0;i<connectionsStr.length;i++){
        if(connectionsStr[i]==null){
          connectionsStr[i]="0";
        }
      }
      Arrays.sort(connectionsStr);
      return connectionsStr;
    }
    
    /**
     * outputMessage
     * 
     * out print the message 
     * @param      message 
     *@param      isnew  true means renew ,fasle means append
     * @return  void
     */   
    public void outputMessage(String message, boolean isnew){
      Date thisTime = new Date();
      SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss ");      
      if(message.length()>5000){//it means session expired
        message = AppletResource.lableArr[209];
        messageTextArea.append(df.format(thisTime));
        messageTextArea.append(message);
        messageTextArea.append("\n");
      } else
      {
        messageTextArea.append(df.format(thisTime));
        messageTextArea.append(message);
        messageTextArea.append("\n");
      }
      
      messageTextArea.setSelectionEnd(10000);
      //messageTextArea.
    }
    
    public void clearMessage(){
      messageTextArea.setText("");
    }
    
    public URL getURLByString(String urlString){
        URL url = null;
            
        try{
        //URL openUrl = getURLByString("gif\\Open.gif");
            url =  new URL(hostURL+"/jsp/workflow/client/"+urlString);
        }catch(Exception e){
            System.out.println("Get Icon Error!") ;
        }    
        return url;        
    }
    
    boolean createAutoTaskConnectionType(Port source, DefaultEdge edge){
      DefaultGraphCell cell = (DefaultGraphCell)((DefaultPort)source).getParent();
      GPUserObject userObject;
      if(cell.getUserObject() instanceof GPUserObject){
        userObject = (GPUserObject)cell.getUserObject();
      } else {
        userObject =new GPUserObject();
      }
      ObjectInputStream inputFromServlet = null;
      String stepType = (String)userObject.getProperty("STEPTYPE");
      String actionID;
      if(stepType!=null&&stepType.substring(0,1).equals("C")){
        actionID=stepType.substring(1);
      } else {
        actionID="13";
      }
      String[] actionRouteLable=null;
      String getDataURL  = "/workflow/appletMiddleware?dataType=WORKFLOW_ACTION&ACTIONID="+actionID;
      try{
        inputFromServlet = httpOperation.getObjectInputStreamFromServlet(getDataURL);
        if(inputFromServlet == null){
          return false;
        }    
        Object obj = null;
        //obj = inputFromServlet.readObject();
      //  get bind list for select
        obj = inputFromServlet.readObject();
        if (obj instanceof String[]) {
          actionRouteLable = (String[]) obj;
        } else if (obj instanceof Exception) {
          //otherwise type cast it to Exception and throw that exception.
          throw (Exception) obj;
        }   
      }catch(Exception e){
        e.printStackTrace();
        return false;
      }
      if(!Utility.isEmpty(stepType)){
        try{
          if(stepType.substring(0,1).equals(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO)){
            
            RouteWindow routeWindow = new RouteWindow(null, AppletResource.lableArr[161], true);
            routeWindow.setBounds(Editor.this.getX(),Editor.this.getY(),350,200);
            routeWindow.setLocationRelativeTo(Editor.this);
            routeWindow.setEdge(edge);
            routeWindow.setActionType(actionType);
            
            routeWindow.initData();
            routeWindow.show();
          } else {
            outputMessage(AppletResource.lableArr[210], false);
            return false;
          }
        }catch(Exception e){
          e.printStackTrace();
        }
      } else {
        outputMessage(AppletResource.lableArr[210], false);
        return false;
      }     
      return true;
    }
    
    public HttpOperation getHttpOperation(){
      return this.httpOperation;
    }
    
    public void setHttpOperation(HttpOperation httpOperation){
      this.httpOperation=httpOperation;
    }
    
    public GPGraph getGraph(){
      return this.graph;
    }        
    
    public void setGraph(GPGraph graph){
      this.graph=graph;
    }    
  }